﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VRacer;
using System.Collections.ObjectModel;
using System.Windows.Media.Animation;


namespace VRacer.Controls
{
    /// <summary>
    /// Interaction logic for GBPlayerPath.xaml
    /// </summary>
    public partial class GBPlayerPath : UserControl
    {
        public static readonly DependencyProperty PlayerProperty = DependencyProperty.Register("Player", typeof(PlayerBase), typeof(GBPlayerPath), new PropertyMetadata(new PropertyChangedCallback(PlayerChanged)));

        public static readonly RoutedEvent ActivatedEvent = EventManager.RegisterRoutedEvent("Activated", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(GBPlayerPath));
        public static readonly RoutedEvent DeactivatedEvent = EventManager.RegisterRoutedEvent("Deactivated", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(GBPlayerPath));


        public GBPlayerPath()
        {
            InitializeComponent();
            Business.Instance.Game.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Game_PropertyChanged);
        }

        void Game_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "State")
            {
                UpdatePredictionBox();
            }
        }

        protected void UpdatePredictionBox()
        {
            if (Business.Instance.Game.State != GameState.Started || Player is RemotePlayer)
                _nextMoveCanvas.Visibility = Visibility.Collapsed;
            else
            {
                _nextMoveCanvas.Visibility = Visibility.Visible;

                Canvas.SetLeft(_nextMovePreview, (Player.ResultantPosition.X - 1) * 10);
                Canvas.SetTop(_nextMovePreview, (Player.ResultantPosition.Y - 1) * 10);

                _nextMove11.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X - 1, Player.ResultantPosition.Y - 1)).X == -1;
                _nextMove12.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X, Player.ResultantPosition.Y - 1)).X == -1;
                _nextMove13.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X + 1, Player.ResultantPosition.Y - 1)).X == -1;
                _nextMove21.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X - 1, Player.ResultantPosition.Y)).X == -1;
                _nextMove22.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X, Player.ResultantPosition.Y)).X == -1;
                _nextMove23.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X + 1, Player.ResultantPosition.Y)).X == -1;
                _nextMove31.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X - 1, Player.ResultantPosition.Y + 1)).X == -1;
                _nextMove32.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X, Player.ResultantPosition.Y + 1)).X == -1;
                _nextMove33.IsEnabled = Business.Instance.Game.GetCollisionPoint(Player, new Point(Player.ResultantPosition.X + 1, Player.ResultantPosition.Y + 1)).X == -1;
            }
        }


        private static void PlayerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PlayerBase oldPlayer = (PlayerBase)e.OldValue;
            PlayerBase newPlayer = (PlayerBase)e.NewValue;
            (d as GBPlayerPath).PlayerChanged(oldPlayer, newPlayer);
        }

        private void PlayerChanged(PlayerBase oldPlayer, PlayerBase newPlayer)
        {
            if (oldPlayer != null)
            {
                //oldPlayer.Moved -= player_Moved;

            }
            else
            {
                //(Resources["_ellipses"] as Style).Setters.Add(new Setter(new SolidColorBrush(Player.Color),));
                //_path.Stroke = new SolidColorBrush(Player.Color);
                _pathFigure.StartPoint = new Point(Player.Position.X * 10, Player.Position.Y * 10);
                _pathFigure.Segments.Remove(_line);
            }

            newPlayer.Activated += new EventHandler(newPlayer_Activated);
            newPlayer.Deactivated += new EventHandler(newPlayer_Deactivated);
            newPlayer.Crashed += new EventHandler<PlayerCrashedEventArgs>(newPlayer_Crashed);
            newPlayer.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(newPlayer_PropertyChanged);

            UpdatePredictionBox();

            this.DataContext = newPlayer;
        }

        void newPlayer_Crashed(object sender, PlayerCrashedEventArgs e)
        {

        }

        void newPlayer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Dispatcher.Invoke((DefaultDelegate)(() =>
                {

                    if (e.PropertyName == "ResultantPosition")
                        UpdatePredictionBox();
                    else if (e.PropertyName == "Position")
                    {
                        if (Business.Instance.Game.State != GameState.Started)
                        {
                            _pathFigure.StartPoint = new Point(Player.Position.X * 10, Player.Position.Y * 10);
                            return;
                        }

                        //usuwanie starszych linii
                        if (_pathFigure.Segments.Count > 10)
                        {
                            _pathFigure.StartPoint = (_pathFigure.Segments[0] as LineSegment).Point;
                            _pathFigure.Segments.RemoveAt(0);
                        }

                        _pointAnimation.From = _pathFigure.Segments.Count > 0 ? (_pathFigure.Segments.Last() as LineSegment).Point : _pathFigure.StartPoint;
                        _pointAnimation.To = new Point(Player.Position.X * 10, Player.Position.Y * 10);

                        _pathFigure.Segments.Add(new LineSegment(_pointAnimation.From.Value, true));
                        _pathFigure.Segments.Last().BeginAnimation(LineSegment.PointProperty, _pointAnimation);
                    }
                    else if (e.PropertyName == "BestNewPosition" && Player is NoobPlayer)
                    {
                        var player = Player as NoobPlayer;

                        Canvas.SetLeft(_bestMove, player.BestNewPosition.X * 10);
                        Canvas.SetTop(_bestMove, player.BestNewPosition.Y * 10);
                    }
                }));
        }

        void newPlayer_Deactivated(object sender, EventArgs e)
        {
            Dispatcher.Invoke((DefaultDelegate)(() =>
               {
                   _nextMovePreview.Visibility = Visibility.Collapsed;
                   _bestMove.Visibility = Visibility.Collapsed;
                   RaiseEvent(new RoutedEventArgs(GBPlayerPath.DeactivatedEvent));
               }));

        }

        void newPlayer_Activated(object sender, EventArgs e)
        {
            Dispatcher.Invoke((DefaultDelegate)(() =>
              {
                  _nextMovePreview.Visibility = Visibility.Visible;
                  RaiseEvent(new RoutedEventArgs(GBPlayerPath.ActivatedEvent));

                  if (Player is NoobPlayer)
                      _bestMove.Visibility = Visibility.Visible;
                  else
                      _bestMove.Visibility = Visibility.Collapsed;
              }));

        }

        public PlayerBase Player
        {
            get { return (PlayerBase)GetValue(PlayerProperty); }
            set { SetValue(PlayerProperty, value); }
        }

    }
}
